﻿#region

using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using HibernatingRhinos.Profiler.Appender.NHibernate;
using MediaSage.Lib;
using MediaSage.Lib.Configuration;
using MediaSage.Lib.Database;
using MediaSage.Lib.Plugin;
using MediaSage.Lib.Utilities;
using Microsoft.VisualStudio.TestTools.UnitTesting;

#endregion

namespace TMDBProviderTests
{
    [TestClass]
    public class TMDBProviderTest
    {
        #region Fields

        public static Config config;
        public static PluginBase provider;

        #endregion Fields

        #region Methods

        [ClassInitialize]
        public static void LoadConfiguration(TestContext testContext)
        {
            NHibernateProfiler.Initialize();
            config = new Config();
            config.GetAllImages = true;
            config.ImageDir = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Images");
            Directory.CreateDirectory(config.ImageDir);
            var PE = new PluginEntity();
            PE.Location = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location),
                                       "TMDBProvider.dll");
            provider = Plugin.LoadPlugin(config, PE);
        }

        [TestMethod]
        [DeploymentItem("TMDBProvider.Dll")]
        public void TestGetMoviesTMDBNoImages()
        {
            NHibernateProfiler.Initialize();
            List<MediaSearchReturn> test = provider.SearchForMediaByName("Rambo");
            foreach (MediaSearchReturn msr in test)
            {
                int medId;
                MediaClass mc = provider.GetMediaByID(msr.TMDBID);
                if (mc == null)
                {
                    Assert.Fail("Failed to download: " + msr.name);
                }
                if (mc.StoreToDatabase() == false)
                {
                    Assert.Fail("Failed to save to database");
                }

                var db = new Database(config);

                MediaClass dbMC = db.GetMovieByTMDBID(msr.TMDBID);
                if (dbMC == null)
                {
                    Assert.Fail("Failed to load back Database object");
                }
                Assert.AreEqual(dbMC.Images.Count, mc.Images.Count,
                                String.Format(
                                    "Image count between returned value and db value different.  Returned count: %d, DB count: %d",
                                    mc.Images.Count, dbMC.Images.Count));
                Assert.AreEqual(dbMC.Cast.Count, mc.Cast.Count,
                                String.Format(
                                    "Cast count between returned value and db value differ.  Returned count: %d, DB count: %d",
                                    dbMC.Cast.Count, mc.Cast.Count));
                foreach (PersonEntity pe in mc.Cast)
                {
                    PersonEntity dbPE = null;
                    foreach (PersonEntity dPE in dbMC.Cast)
                    {
                        if (dPE.TMDBID == pe.TMDBID)
                        {
                            dbPE = dPE;
                        }
                    }
                    Assert.AreEqual(pe, dbPE,
                                    String.Format("Did not find person: %s in Database for retrieved movie", pe.Name));
                    Assert.AreEqual(pe.Images.Count, dbPE.Images.Count,
                                    String.Format(
                                        "Image count differs for person: %s, retrieved count: %d, DB count %s", pe.Name,
                                        pe.Images.Count, dbPE.Images.Count));
                }
            }
        }

        [TestMethod]
        [DeploymentItem("TMDBProvider.Dll")]
        public void TestGetMoviesTMDBWithImages()
        {
            NHibernateProfiler.Initialize();
            provider.EnableImageDownloads(true);
            List<MediaSearchReturn> test = provider.SearchForMediaByName("Rambo");
            foreach (MediaSearchReturn msr in test)
            {
                int medId;
                MediaClass mc = provider.GetMediaByID(msr.TMDBID);
                if (mc == null)
                {
                    Assert.Fail("Failed to download: " + msr.name);
                }
                if (mc.StoreToDatabase() == false)
                {
                    Assert.Fail("Failed to save to database");
                }

                var db = new Database(config);

                MediaClass dbMC = db.GetMovieByTMDBID(msr.TMDBID);
                if (dbMC == null)
                {
                    Assert.Fail("Failed to load back Database object");
                }
                Assert.AreEqual(dbMC.Images.Count, mc.Images.Count,
                                String.Format(
                                    "Image count between returned value and db value different.  Returned count: %d, DB count: %d",
                                    mc.Images.Count, dbMC.Images.Count));
                Assert.AreEqual(dbMC.Cast.Count, mc.Cast.Count,
                                String.Format(
                                    "Cast count between returned value and db value differ.  Returned count: %d, DB count: %d",
                                    dbMC.Cast.Count, mc.Cast.Count));
                foreach (PersonEntity pe in mc.Cast)
                {
                    PersonEntity dbPE = null;
                    foreach (PersonEntity dPE in dbMC.Cast)
                    {
                        if (dPE.TMDBID == pe.TMDBID)
                        {
                            dbPE = dPE;
                        }
                    }
                    Assert.AreEqual(pe, dbPE,
                                    String.Format("Did not find person: %s in Database for retrieved movie", pe.Name));
                    Assert.AreEqual(pe.Images.Count, dbPE.Images.Count,
                                    String.Format(
                                        "Image count differs for person: %s, retrieved count: %d, DB count %s", pe.Name,
                                        pe.Images.Count, dbPE.Images.Count));
                }
            }
        }

        [TestMethod]
        [DeploymentItem("TMDBProvider.Dll")]
        public void TestGetVersion()
        {
            VersionInfo vi = provider.GetVersionInfo();
            Assert.AreEqual(vi.Name, "TMDBProvider");
            Assert.AreEqual(vi.MajorVersion, 0);
            Assert.AreEqual(vi.MinorVersion, 9);
        }

        [TestMethod]
        [DeploymentItem("TMDBProvider.Dll", "TestData")]
        public void TestSendingInvalidValueForGetMediaById()
        {
            try
            {
                provider.GetMediaByID("test");
                Assert.Fail("GetMediaByID(\"test\") should have thrown an ArgumentException");
            }
            catch (ArgumentException)
            {
            }
        }

        [TestMethod]
        [DeploymentItem("TMDBProvider.Dll")]
        public void TestTMDBSearchByName()
        {
            List<MediaSearchReturn> test = provider.SearchForMediaByName("Rambo");
            Assert.IsTrue(test.Count > 0);
            MediaSearchReturn previous = null;
            foreach (MediaSearchReturn msr in test)
            {
                if (previous != null)
                {
                    if (msr.pctLikelyMatch > previous.pctLikelyMatch)
                    {
                        Assert.Fail("Return values not sorted in descending order");
                    }
                    if (msr.pctLikelyMatch > 100 || msr.pctLikelyMatch < 0)
                    {
                        Assert.Fail("pcLikelyMatch invalid value (" + msr.pctLikelyMatch + "), must be 100<=x>=0");
                    }
                }
                previous = msr;
            }

            List<MediaSearchReturn> test1 = provider.SearchForMediaByNameAndYear("Rambo", 2008);
            Assert.IsTrue(test1.Count > 0);
            previous = null;
            foreach (MediaSearchReturn msr in test1)
            {
                if (previous != null)
                {
                    if (msr.pctLikelyMatch > previous.pctLikelyMatch)
                    {
                        Assert.Fail("Return values not sorted in descending order");
                    }
                    if (msr.pctLikelyMatch > 100 || msr.pctLikelyMatch < 0)
                    {
                        Assert.Fail("pcLikelyMatch invalid value (" + msr.pctLikelyMatch + "), must be 100<=x>=0");
                    }
                }
                previous = msr;
            }
        }

        [TestMethod]
        [DeploymentItem("TMDBProvider.Dll")]
        public void TestGetTMDBMovie()
        {
            MediaClass media = provider.GetMediaByID(11);
        }

        [TestMethod]
        [DeploymentItem("TMDBProvider.Dll")]
        public void TestGetTMDBMovieByMediaObject()
        {
            MediaClass media = new MediaClass(config);
            media.IMDBID="tt0083866";
            media = provider.GetMedia(media, MediaMergeType.WRITE_ONLY_ON_NULL_OR_EMPTY);

        }

        [TestMethod]
        [DeploymentItem("TMDBProvider.Dll")]
        public void TestSearchTMDBMovieByMediaObject_IMDBID()
        {
            MediaClass media = new MediaClass(config);
            media.IMDBID = "tt0083866";
            List<MediaSearchReturn> msr = provider.SearchForMedia(media);
            Assert.AreEqual(601, msr[0].TMDBID, String.Format("Expected 601 for the TMDBID, got {0}", msr[0].TMDBID));
            Assert.AreEqual(100, msr[0].pctLikelyMatch, "Expected a 100% match for first result");
        }

        [TestMethod]
        [DeploymentItem("TMDBProvider.Dll")]
        public void TestSearchTMDBMovieByMediaObject_TMDBID()
        {
            MediaClass media = new MediaClass(config);
            media.TmdbID = 87826;
            List<MediaSearchReturn> msr = provider.SearchForMedia(media);
            Assert.AreEqual("tt1648179", msr[0].IMDBID,
                            String.Format("Expected tt1648179 for the IMDBID, got {0}", msr[0].IMDBID));
            Assert.AreEqual(100, msr[0].pctLikelyMatch, "Expected a 100% match for first result");
        }

        [TestMethod]
        [DeploymentItem("TMDBProvider.Dll")]
        public void TestSearchTMDBMovieByMediaObject_TitleAndDate()
        {
            MediaClass media = new MediaClass(config);

            media.Title = "Rocky";
            media.Released = new DateTime(1976, 1, 1);
            media.TmdbID = 0;
            List<MediaSearchReturn> msr = provider.SearchForMedia(media);
            Assert.AreEqual(1366, msr[0].TMDBID, String.Format("Expected 1366 for TMDBID, got {0}", msr[0].TMDBID));

        }

        [TestMethod]
        [DeploymentItem("TMDBProvider.Dll")]
        public void TestSearchTMDBMovieByMediaObject_Title()
        {
            MediaClass media = new MediaClass(config);
            
            media.Title = "Rocky";
            List<MediaSearchReturn> msr = provider.SearchForMedia(media);
            Assert.AreEqual(1366, msr[0].TMDBID, String.Format("Expected 1366 for TMDBID, got {0}", msr[0].TMDBID));
        }


        #endregion Methods
    }
}